diff options
Diffstat (limited to 'src/routes/user/[user]')
| -rw-r--r-- | src/routes/user/[user]/+page.svelte | 93 |
1 files changed, 91 insertions, 2 deletions
diff --git a/src/routes/user/[user]/+page.svelte b/src/routes/user/[user]/+page.svelte index 097007f0..3c443ae6 100644 --- a/src/routes/user/[user]/+page.svelte +++ b/src/routes/user/[user]/+page.svelte @@ -20,6 +20,7 @@ import SvelteMarkdown from 'svelte-markdown'; import MarkdownLink from '$lib/MarkdownLink.svelte'; import LinkedTooltip from '$lib/Tooltip/LinkedTooltip.svelte'; + import type { DragEventHandler } from 'svelte/elements'; export let data; @@ -27,6 +28,8 @@ let error = false; let schedule: ParseResult | undefined = undefined; let preferences: UserPreferences | undefined = undefined; + let draggedCategory: string | null = null; + let draggedOverCategory: string | null = null; $: displayBadges = (username: string, badges: number | string) => $locale({ @@ -42,6 +45,81 @@ .catch(() => (error = true)); }); + const handleDragStart = ( + event: DragEvent & { currentTarget: EventTarget & HTMLDivElement }, + category: string | null + ) => { + draggedCategory = category; + + if (event.dataTransfer) event.dataTransfer.effectAllowed = 'move'; + }; + + const handleDragOver = (event: any) => { + event.preventDefault(); + + event.dataTransfer.dropEffect = 'move'; + }; + + const handleDragEnter = ( + event: DragEvent & { currentTarget: EventTarget & HTMLDivElement }, + category: string | null + ) => { + event.preventDefault(); + + if (draggedCategory !== category && preferences && draggedCategory) { + draggedOverCategory = category; + + const categories = preferences.pinned_badge_wall_categories.split(','); + const draggedIndex = categories.indexOf(draggedCategory); + const targetIndex = categories.indexOf(category); + + categories.splice(draggedIndex, 1); + categories.splice(targetIndex, 0, draggedCategory); + + preferences.pinned_badge_wall_categories = categories.join(','); + } + }; + + const handleDragLeave = ( + event: DragEvent & { currentTarget: EventTarget & HTMLDivElement }, + category: string + ) => { + event.preventDefault(); + + if (draggedOverCategory === category && preferences && draggedCategory) { + draggedOverCategory = null; + + const categories = preferences.pinned_badge_wall_categories.split(','); + const draggedIndex = categories.indexOf(draggedCategory); + + categories.splice(draggedIndex, 1); + categories.splice(categories.indexOf(category) + 1, 0, draggedCategory); + + preferences.pinned_badge_wall_categories = categories.join(','); + } + }; + + const handleDrop = (event: { preventDefault: () => void }) => { + event.preventDefault(); + + if (userData && preferences) { + fetch( + root( + `/api/preferences?id=${userData.id}&setCategories=${preferences.pinned_badge_wall_categories}` + ), + { + method: 'PUT', + headers: { + 'Content-Type': 'application/json' + } + } + ).then(refreshPreferences); + } + + draggedCategory = null; + draggedOverCategory = null; + }; + onMount(async () => { schedule = typeSchedule( parseScheduleHtml( @@ -248,10 +326,21 @@ <div class="pinned-categories"> {#each preferences.pinned_badge_wall_categories.split(',') as category} - <span class="card card-small pinned-category"> + <div + class="card card-small pinned-category" + draggable="true" + on:dragstart={(event) => handleDragStart(event, category)} + on:dragover={handleDragOver} + on:dragenter={(event) => handleDragEnter(event, category)} + on:dragleave={(event) => handleDragLeave(event, category)} + on:drop={handleDrop} + role="button" + tabindex="0" + > <span class="pinned-category-name"> {category} </span> + <button on:click={() => { if (userData) @@ -260,7 +349,7 @@ }).then(refreshPreferences); }}>Remove</button > - </span> + </div> {/each} <span class="card card-small pinned-category"> |